package tech.youai.ppping;

import com.binarywang.spring.starter.wxjava.cp.properties.WxCpProperties;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import me.chanjar.weixin.cp.api.WxCpOAuth2Service;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.bean.article.NewArticle;
import me.chanjar.weixin.cp.bean.message.WxCpMessage;
import me.chanjar.weixin.cp.bean.message.WxCpMessageSendResult;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;

import org.springframework.util.StringUtils;
import tech.youai.nav.*;

import javax.annotation.PreDestroy;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.*;

public class Weixin {
    static final Logger logger = LoggerFactory.getLogger(Weixin.class);
//    final static int DESCRIPTION_MAX_LENGTH = 512;
    private final Configuration weixinProperties;
    private WxCpService wxCpService = null;
//    private WxCpService wxCpNewsService = null;
    private ExecutorService messageQueue;
//    private final ApplicationEventPublisher applicationEventPublisher;
    private final UrlBuilderFactory urlBuilderFactory;

    public Weixin(Configuration weixinProperties, UrlBuilderFactory urlBuilderFactory){
        this.weixinProperties = weixinProperties;
//        this.applicationEventPublisher = applicationEventPublisher;
        this.urlBuilderFactory = urlBuilderFactory;
//        messageQueue = Executors.newFixedThreadPool(10);
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("weixin-pool-%d").build();
        messageQueue = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
    }
    public WxCpService getWxCpService(){
        if(wxCpService==null && StringUtils.hasLength(weixinProperties.getCorpId())){
            WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();
            config.setCorpId(weixinProperties.getCorpId());      // 设置微信企业号的appid
            config.setCorpSecret(weixinProperties.getCorpSecret());  // 设置微信企业号的app corpSecret
            //config.setAgentId(weixinProperties.getAgentId());     // 设置微信企业号应用ID
            //config.setToken(weixinProperties.getToken());       // 设置微信企业号应用的token
            //config.setAesKey(weixinProperties.getAesKey());      // 设置微信企业号应用的EncodingAESKey

            wxCpService = new WxCpServiceImpl();
            wxCpService.setWxCpConfigStorage(config);
        }

        return wxCpService;
    }
//    public WxCpService getWxCpNewsService(){
//        if(wxCpNewsService==null && !StringUtils.isEmpty(weixinProperties.getCorpId())){
//            WxCpDefaultConfigImpl config = new WxCpDefaultConfigImpl();
//            config.setCorpId(weixinProperties.getCorpId());      // 设置微信企业号的appid
//            String secret = !StringUtils.isEmpty(weixinProperties.getNewsAgentSecret()) ?
//                    weixinProperties.getNewsAgentSecret() : weixinProperties.getCorpSecret();
//            config.setCorpSecret(secret);  // 设置微信企业号的app corpSecret
//            //config.setAgentId(weixinProperties.getNewsAgentId());     // 设置微信企业号应用ID
//            //config.setToken(weixinProperties.getToken());       // 设置微信企业号应用的token
//            //config.setAesKey(weixinProperties.getAesKey());      // 设置微信企业号应用的EncodingAESKey
//
//            wxCpNewsService = new WxCpServiceImpl();
//            wxCpNewsService.setWxCpConfigStorage(config);
//        }
//
//        return wxCpNewsService;
//    }

//    @Override
//    public void publishNews(Long id, String title, String content) {
//        publishNews(id, title, content, null);
//    }

//    @Override

    public void noticeUser(String toUser,  String content) {
        noticeUser(toUser, null, content, null);
    }
    public void noticeUser(String toUser, String title, String content) {
        noticeUser(toUser, content, title, null);
    }


    @PreDestroy
    public void shutdown(){
        messageQueue.shutdown();
        //DefaultApacheHttpClientBuilder.get().getIdleConnectionMonitorThread().shutdown();
    }
//
//    private void tryPublishNewsToWeixin(String title, String msgContent, UrlInfo urlInfo) {
//        try{
//            WxCpService svc = getWxCpNewsService();
//            if(svc!=null){
//
//                NewArticle article = new NewArticle();
//                article.setTitle(title);
//                String content =  msgContent;
//                if(content!=null && content.length()>0) {
//                    if (content.length() > DESCRIPTION_MAX_LENGTH) content = content.substring(0, DESCRIPTION_MAX_LENGTH - 1);
//                    article.setDescription(appendTime(content));
//                }
//                setArticleUrl(urlInfo, svc, article);
//
//                Integer newAgentId = Integer.parseInt(weixinProperties.getNewsAgentId());
//                WxCpMessage message = WxCpMessage.NEWS()
//                        .agentId(newAgentId)
//                        .toUser("@all")
//                        .addArticle(article)
//                        .build();
//                svc.getMessageService().send(message);
//            }
//        }catch (Exception ex){
//            ex.printStackTrace();
//        }
//    }

    private void setArticleUrl(UrlInfo urlInfo, WxCpService svc, NewArticle article) throws UnsupportedEncodingException {
        if (urlInfo != null) {
            UrlBuilder urlBuilder = this.urlBuilderFactory.getUrlBuilder(urlInfo.getUrlBuilder());
            if(urlBuilder==null){
                urlBuilder = this.urlBuilderFactory.getDefaultUrlBuilder();
            }
            String redirectUrl = urlBuilder.build(urlInfo);
            //UriTemplate uriTemplate = new UriTemplate(weixinProperties.getNewsUrlTemplate());
            if (!StringUtils.isEmpty(redirectUrl)) {
                redirectUrl = java.net.URLEncoder.encode(redirectUrl, "utf-8");
//                String rawUrl = authorizationUrl + "?redirectUrl=" + redirectUrl;
                WxCpOAuth2Service oauth2 = svc.getOauth2Service();
                String url = oauth2.buildAuthorizationUrl(redirectUrl, null);
                article.setUrl(url);
                article.setDescription(article.getDescription()+ "\n(可点击此消息进入)");
            }else{
                System.out.println("---注意：无链接的消息提醒---！");
            }


        }
    }

//    @Override
    public void noticeUser(String toUser, String content, UrlInfo urlInfo) {
        noticeUser(toUser, null, content, urlInfo);

    }
    public void noticeUser(String toUser,String title, String content, UrlInfo urlInfo) {
        //0点到7点不发送
        int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        if(hour>=0 && hour<7){
            logger.info("0点到7点不发送消息");
            return;
        }
//        if(weixinProperties.getEnableNotify()==false){
//            System.out.println("已禁用提醒消息发送！");
//            System.out.println("CorpId:" + weixinProperties.getCorpId());
//            System.out.println("toUser：" + toUser);
//            System.out.println("content:" + content);
//            System.out.println("============");
//            System.out.println();
//            return;
//        }
        messageQueue.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {

                String msgContent = appendTime(content);
                tryNoticeUserWithWeixin(toUser,title, msgContent, urlInfo);

//                try{
//                    NoticeUserEvent event = new NoticeUserEvent(this);
//                    event.setToUser(toUser);
//                    event.setContent(msgContent);
//                    event.setUrlInfo(urlInfo);
//                    applicationEventPublisher.publishEvent(event);
//                }catch (Throwable ex){
//                    ex.printStackTrace();
//                }

                return null;
            }
        });
    }

    private void tryNoticeUserWithWeixin(String toUser, String tilte, String msgContent, UrlInfo urlInfo) {
        if(StringUtils.isEmpty(toUser)){
            System.out.println("取消发送微信消息，toUser为空！msgContent："+msgContent);
            return;
        }
        try {
            WxCpService svc = getWxCpService();
            if(svc!=null){
                //TODO: 临时调试
                System.out.println("发送微信消息：");
                System.out.println("CorpId:" + weixinProperties.getCorpId());
                System.out.println("toUser：" + toUser);
                System.out.println("content:" + msgContent);

                Integer agentId = StringUtils.isEmpty(weixinProperties.getAgentId()) ? 0 : weixinProperties.getAgentId();

//                WxCpMessage message = WxCpMessage.TEXT()
//                        .toUser(toUser)
//                        .agentId(agentId)
//                        .content(msgContent)
//                        .build();
//
//                svc.messageSend(message);
                NewArticle article = new NewArticle();
                article.setTitle(appendTime(StringUtils.hasLength(tilte)?tilte:"系统任务", false));
                String content =  msgContent;
                if(content!=null && content.length()>0) {
//                    if (content.length() > DESCRIPTION_MAX_LENGTH) content = content.substring(0, DESCRIPTION_MAX_LENGTH - 1);
                    article.setDescription(content);
                }
                setArticleUrl(urlInfo, svc, article);

                WxCpMessage message = WxCpMessage.NEWS()
                        .agentId(agentId)
                        .toUser(toUser)
                        .addArticle(article)
                        .build();


                WxCpMessageSendResult result = svc.getMessageService().send(message);

                StringBuilder printInfo = new StringBuilder();
                printInfo.append("发送消息完成，");
                boolean hasInvalidUser = !StringUtils.isEmpty(result.getInvalidUser());
                boolean hasInvalidUserList = (result.getInvalidUserList()!=null && result.getInvalidUserList().size()>0);
                if(hasInvalidUser || hasInvalidUserList){
                    printInfo.append("但以下用户在企业号中不存在：");
                    if(hasInvalidUser){
                        printInfo.append("(InvalidUser)"+result.getInvalidUser());
                    }
                    if(hasInvalidUserList){
                        if(hasInvalidUser){
                            printInfo.append(",");
                        }
                        printInfo.append("(InvalidUserList)");
                        for (int i = 0; i < result.getInvalidUserList().size(); i++) {
                            if(i>0){
                                printInfo.append(",");
                            }
                            printInfo.append(result.getInvalidUserList().get(i));
                        }
                    }
                }else{
                    printInfo.append("以下用户接收成功："+toUser);
                }
                if(printInfo.length()>0){
                    System.out.println(printInfo);
                }
            }
        } catch (Exception e) {
            System.out.println("发送消息" + toUser + "出错！");
            e.printStackTrace();
        }
    }


//    @Autowired
//    public void setWeixinProperties(WeixinProperties weixinProperties) {
//        this.weixinProperties = weixinProperties;
//    }

    private String appendTime(String content){
        return appendTime(content, true);
    }
    private String appendTime(String content, boolean newLine){
            Date now = new Date();
        SimpleDateFormat df = new SimpleDateFormat("[yyyy-MM-dd HH:mm]");
        String time = df.format(now);
        String msgContent = time;
        if(newLine){
            msgContent += '\n';
        }
        msgContent += content;
        return msgContent;
    }

    public static void main(String[] args) {
        Configuration props = new Configuration();
        props.setCorpId("wxa084413e14cf0b0d");
        props.setCorpSecret("JeSVuPDu7DI-2uiJ3Rcej34nWzdkUjpIjiquzDrJsII6XmaEzxaWxuu6c0MHnEMX");
        Weixin weixin = new Weixin(props, new SimpleUrlBuilderFactory());
        weixin.noticeUser("ayi","警报警报!", "众联系统无法访问！", new UrlInfo("http://youai.net.cn/login"));
    }
}
